package com.atguigu.exam.service.impl;


import com.atguigu.exam.entity.ExamRecord;
import com.atguigu.exam.entity.Paper;
import com.atguigu.exam.entity.PaperQuestion;
import com.atguigu.exam.entity.Question;
import com.atguigu.exam.mapper.ExamRecordMapper;
import com.atguigu.exam.mapper.PaperMapper;
import com.atguigu.exam.mapper.PaperQuestionMapper;
import com.atguigu.exam.mapper.QuestionMapper;
import com.atguigu.exam.service.PaperQuestionService;
import com.atguigu.exam.service.PaperService;
import com.atguigu.exam.vo.PaperVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
 * 试卷服务实现类
 */
@Slf4j
@Service
public class PaperServiceImpl extends ServiceImpl<PaperMapper, Paper> implements PaperService {

    @Autowired
    private PaperQuestionService paperQuestionService;

    @Autowired
    private ExamRecordMapper examRecordMapper;

    //获取试卷详情
    @Override
    public Paper getDetailsById(Integer id) {
        Paper paper=baseMapper.getDetailsById(id);
        return paper;
    }

    /*创建试卷
        思路:1,先判断有没有相同名字的试卷
        2,创建一个paper类型的对象，将paperVo中的相同属性复制给paper对象，获取并设置status,totalScore,questionCount
        3，把题放到paper_question表中，将 Map<Integer, BigDecimal> 转换为 List<PaperQuestion>
     */
    @Override
    public void createPaper(PaperVo paperVo) {
        boolean exists = baseMapper.exists(new LambdaQueryWrapper<Paper>().eq(Paper::getName, paperVo.getName()));
        if( exists){
            throw new RuntimeException("试卷已存在，不能创建");
        }
        //创建paper对象
        Paper paper = new Paper();
        //使用工具类将paperVo中的相同属性复制给paper
        BeanUtils.copyProperties(paperVo,paper);
        //设置试卷状态
        paper.setStatus("DRAFT");
        //获取当前试卷的所有题目
        Map<Integer, BigDecimal> questions = paperVo.getQuestions();
        //获取总分，reduce 将 questions.values() 集合中的所有 BigDecimal 值进行累加求和，questions.values()获取的是分数
        BigDecimal totalScore = questions.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        //设置总分
        paper.setTotalScore(totalScore);
        //设置题目数量
        paper.setQuestionCount(questions.size());
        //保存试卷
        baseMapper.insert(paper);
        //将 Map<Integer, BigDecimal> 转换为 List<PaperQuestion>
        //entrySet()是获取键值对集合，同时访问键和值
        List<PaperQuestion> paperQuestionList= questions.entrySet().stream().map(entry -> {
            //创建一个PaperQuestion对象
            PaperQuestion paperQuestion = new PaperQuestion(paper.getId(), Long.valueOf(entry.getKey()), entry.getValue());
            return paperQuestion;
        }).collect(Collectors.toList());
        //批量保存
        paperQuestionService.saveBatch(paperQuestionList);
    }

    /*更新试卷
       思路：1,有相同名字的不能更新，状态是已发布的不能更新
       2，与添加功能一致,要把中间表的数据删除，再添加
     */
    @Override
    public void updatePaper(Integer id, PaperVo paperVo) {
        boolean exists = baseMapper.exists(new LambdaQueryWrapper<Paper>().eq(Paper::getName, paperVo.getName()).ne(Paper::getId, id));
        if( exists){
            throw new RuntimeException("试卷已存在，不能更新");
        }
        //根据id获取数据库中的试卷
        Paper paper = baseMapper.selectById(id);
        if(paper.getStatus().equals("PUBLISHED")){
            throw new RuntimeException("试卷已发布，不能更新");
        }
        //使用工具类将paperVo中的相同属性复制给paper
        BeanUtils.copyProperties(paperVo,paper);
        //获取当前试卷的所有题目
        Map<Integer, BigDecimal> paperVoQuestions = paperVo.getQuestions();
        //获取总分
        BigDecimal totalScore = paperVoQuestions.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        paper.setTotalScore(totalScore);
        //设置题目数量
        paper.setQuestionCount(paperVoQuestions.size());
        baseMapper.updateById(paper);
        //删除中间表数据
        paperQuestionService.remove(new LambdaQueryWrapper<PaperQuestion>().eq(PaperQuestion::getPaperId, id));
        //往中间表插入数据
        List<PaperQuestion> paperQuestionList = paperVoQuestions.entrySet().stream().map(entry -> {
            PaperQuestion paperQuestion = new PaperQuestion(paper.getId(), Long.valueOf(entry.getKey()), entry.getValue());
            return paperQuestion;
        }).collect(Collectors.toList());
        paperQuestionService.saveBatch(paperQuestionList);
    }

    /*删除试卷
       思路：1,判断试卷是否已发布，已发布的不能删除
       2,有考试记录的不能删除
     */
    @Override
    public void deleteById(Integer id) {
        Paper paper = baseMapper.selectById(id);
        if(paper.getStatus().equals("PUBLISHED")){
            throw new RuntimeException("试卷已发布，不能删除");
        }
        Long count = examRecordMapper.selectCount(new LambdaQueryWrapper<ExamRecord>().eq(ExamRecord::getExamId, id));
        if(count>0){
            throw new RuntimeException("该试卷有考试记录，不能删除");
        }
        baseMapper.deleteById(id);
        paperQuestionService.remove(new LambdaQueryWrapper<PaperQuestion>().eq(PaperQuestion::getPaperId, id));
    }

    /*更新试卷状态
       思路：1,如果试卷在考试进行中，则不能改状态
     */
    @Override
    public void updatePaperStatus(Integer id, String status) {
        Long count = examRecordMapper.selectCount(new LambdaQueryWrapper<ExamRecord>().eq(ExamRecord::getExamId, id).eq(ExamRecord::getStatus, "进行中"));
        if(count>0){
            throw new RuntimeException("该试卷有考试进行中，不能修改状态");
        }
        baseMapper.update(null,new LambdaUpdateWrapper<Paper>().eq(Paper::getId, id).set(Paper::getStatus, status));
    }
}